﻿/*
	Copyright (C) 2019 Zongming Liu <1849059316@qq.com>

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License along
	with this program; if not, write to the Free Software Foundation, Inc.,
	51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "Math.h"

#include <cmath>

namespace SkyEngine2d
{
	
	Size::Size()
		:width(0),height(0)
	{
	}
	
	Size::Size(float width,float height)
		:width(width)
		,height(height)
	{
	}
	
	bool Size::operator==(const Size & r)const
	{
		if (this->width==r.width&& this->height ==r.height)
		{
			return true;
		}
		return false;
	}
	
	
	Size Size::operator-(const Vector2& r)
	{
		return Size(this->width - r.x, this->height - r.y);
	}
	
	Size Size::ZERO=Size();
	
	Size& Size::operator=(const Size& size)
	{
		this->width = size.width;
		this->height = size.height;
		return *this;
	}
	
	Size& Size::operator=(const Vector2& size)
	{
		this->width = size.x;
		this->height = size.y;
		return* this;
	}
	
	Rect::Rect()
		:size(), origin() {}
	
	Rect::Rect(float x, float y, float width, float height)
		:size(width,height)
		,origin(x,y)
	{
		
	}
	
	Rect::Rect(float x, float y, const Size & size)
		:origin(x,y)
		,size(size)
	{
	
	}
	
	Rect::Rect(Vector2 pos, const Size&size)
		:origin(pos)
		,size(size)
	{
	
	}
	
	Rect::Rect(const Rect & rect)
		:origin(rect.origin)
		,size(rect.size)
	{
	
	}
	
	void Rect::move(const Vector2 & dt)
	{
		this->origin += dt;
	}
	
	void Rect::move(float x_dt, float y_dt)
	{
		this->origin.x += x_dt;
		this->origin.y += y_dt;
	}
	
	void Rect::moveTo(const Vector2 & pos)
	{
		this->origin = pos;
	}
	
	void Rect::moveTo(float pos_x, float pos_y)
	{
		this->origin.x = pos_x;
		this->origin.y = pos_y;
	}
	
	
	bool Rect::pointOnRect(const Vector2 & point) const
	{
		//点 显然在 左下角的上方
		if (point.x > this->origin.x&&point.y > this->origin.y)
		{
			float topRightX = origin.x + size.width;
			float topRightY = origin.y + size.height;
	
			if (point.x < topRightX&&point.y < topRightY)
			{
				return true;
			}
		}
		return false;
	}
	
	bool Rect::intersectWithLine(const Line & line) const
	{
		Vector2 br(origin.x + size.width, origin.y);
		Vector2 tl(origin.x, origin.y + size.height);
		Vector2 tr(origin.x+size.width,origin.y+size.height);
	
		Line a(origin,br);
		Line b(origin,tl);
		Line c(tl, tr);
		Line d(tr, br);
	
		if (line.lineIntersect(a)||line.lineIntersect(b)||line.lineIntersect(c)||line.lineIntersect(d))
		{
			return true;
		}
	
		return false;
	}
	
	bool Rect::intersectsWithRect(const Rect & rect) const
	{
		return  !(origin.x > rect.origin.x+rect.size.width || 
			origin.y+size.height < rect.origin.y || 
			rect.origin.x > origin.x+size.width ||
			rect.origin.y+size.height < origin.y );
	}
	
	bool Rect::operator==(const Rect & r)
	{
		if (this->origin==r.origin&&this->size==r.size)
		{
			return true;
		}
		return false;
	}
	
	Rect Rect::Zero(0,0,0,0);
	
	
	/////////////////////////////////////////
	
	Line::Line()
	{
	
	}
	
	Line::Line(float x_1, float y_1, float x_2, float y_2)
		:startPos(x_1,y_1)
		,endPos(x_2,y_2)
	{
	
	}
	
	Line::Line(const Vector2& pos_1, const Vector2 & pos_2)
		:startPos(pos_1)
		,endPos(pos_2)
	{
		
	}
	
	Line::~Line()
	{
	
	}
	
	void Line::move(const Vector2 & dt)
	{
		startPos += dt;
		endPos += dt;
	}
	
	bool Line::lineIntersect(const Line & line) const
	{
		//快速排斥实验
		if (max(startPos.x,endPos.x) < min(line.startPos.x,line.endPos.x) ||
			max(startPos.y,endPos.y) < min(line.startPos.y,line.endPos.y) ||
			max(line.startPos.x,line.endPos.x) < min(startPos.x,endPos.x) ||
			max(line.startPos.y,line.endPos.y) < min(startPos.y,endPos.y)
			)
		{
			return false;
		}
	
		//跨立实验
	
		Vector2 u(startPos.x-line.startPos.x,startPos.y-line.startPos.y);
		Vector2 v(startPos.x - line.endPos.x, startPos.y - line.endPos.y);
		Vector2 q(startPos.x - endPos.x, startPos.y - endPos.y);
	
		Vector2 w(endPos.x - line.startPos.x, endPos.y - line.startPos.y);
		Vector2 z(endPos.x - line.endPos.x, endPos.y - line.endPos.y);
		Vector2 p(endPos.x - startPos.x, endPos.y - startPos.y);
	
		if (Vector2::dot(Vector2::cross(u,q),Vector2::cross(v,q))>0
			||Vector2::dot(Vector2::cross(w,p),Vector2::cross(z,p))>0)
		{
			return false;
		}
	
		return true;
	}
}
